home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / Managed / Direct3D / PrtPerVertex / PrtSimulator.cs < prev    next >
Encoding:
Text File  |  2004-09-27  |  19.8 KB  |  536 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: PrtSimulator.cs
  3. //
  4. // Copyright (c) Microsoft Corporation. All rights reserved.
  5. //--------------------------------------------------------------------------------------
  6.  
  7. using System;
  8. using System.IO;
  9. using System.Drawing;
  10. using System.Threading;
  11. using Microsoft.DirectX;
  12. using Microsoft.DirectX.Direct3D;
  13. using Microsoft.Samples.DirectX.UtilityToolkit;
  14.  
  15. namespace PrtPerVertexSample
  16. {
  17.     class SimulatorOptions
  18.     {
  19.         // General settings
  20.         public string InitialDir;
  21.         public string InputMesh;
  22.         public string ResultsFileName;
  23.         public int NumberRays;
  24.         public int Order;
  25.         public int NumberChannels;
  26.         public int NumberBounces;
  27.         public bool IsSubsurfaceScattering;
  28.         public float LengthScale;
  29.         public bool ShowTooltips;
  30.  
  31.         // Material options
  32.         public int PredefinedMaterialIndex;
  33.         public ColorValue Diffuse;
  34.         public ColorValue Absorption;
  35.         public ColorValue ReducedScattering;
  36.         public float RelativeIndexOfRefraction;
  37.  
  38.         // IsAdaptive options
  39.         public bool IsAdaptive;
  40.         public bool IsRobustMeshRefine;
  41.         public float RobustMeshRefineMinEdgeLength;
  42.         public int RobustMeshRefineMaxSubdiv;
  43.         public bool IsAdaptiveDL;
  44.         public float AdaptiveDLMinEdgeLength;
  45.         public float AdaptiveDLThreshold;
  46.         public int AdaptiveDLMaxSubdiv;
  47.         public bool IsAdaptiveBounce;
  48.         public float AdaptiveBounceMinEdgeLength;
  49.         public float AdaptiveBounceThreshold;
  50.         public int AdaptiveBounceMaxSubdiv;
  51.         public string OutputMesh;
  52.         public bool IsBinaryOutputXFile;
  53.     
  54.         // Compression options
  55.         public bool IsSaveCompressedResults;
  56.         public CompressionQuality Quality;
  57.         public int NumberClusters;
  58.         public int NumberPcaVectors;
  59.  
  60.         public SimulatorOptions Clone()
  61.         {
  62.             SimulatorOptions copy = new SimulatorOptions();
  63.  
  64.             // General settings
  65.             copy.InitialDir = InitialDir;
  66.             copy.InputMesh = InputMesh;
  67.             copy.ResultsFileName = ResultsFileName;
  68.             copy.NumberRays = NumberRays;
  69.             copy.Order = Order;
  70.             copy.NumberChannels = NumberChannels;
  71.             copy.NumberBounces = NumberBounces;
  72.             copy.IsSubsurfaceScattering = IsSubsurfaceScattering;
  73.             copy.LengthScale = LengthScale;
  74.             copy.ShowTooltips = ShowTooltips;
  75.  
  76.             // Material options
  77.             copy.PredefinedMaterialIndex = PredefinedMaterialIndex;
  78.             copy.Diffuse = Diffuse;
  79.             copy.Absorption = Absorption;
  80.             copy.ReducedScattering = ReducedScattering;
  81.             copy.RelativeIndexOfRefraction = RelativeIndexOfRefraction;
  82.  
  83.             // IsAdaptive options
  84.             copy.IsAdaptive = IsAdaptive;
  85.             copy.IsRobustMeshRefine = IsRobustMeshRefine;
  86.             copy.RobustMeshRefineMinEdgeLength = RobustMeshRefineMinEdgeLength;
  87.             copy.RobustMeshRefineMaxSubdiv = RobustMeshRefineMaxSubdiv;
  88.             copy.IsAdaptiveDL = IsAdaptiveDL;
  89.             copy.AdaptiveDLMinEdgeLength = AdaptiveDLMinEdgeLength;
  90.             copy.AdaptiveDLThreshold = AdaptiveDLThreshold;
  91.             copy.AdaptiveDLMaxSubdiv = AdaptiveDLMaxSubdiv;
  92.             copy.IsAdaptiveBounce = IsAdaptiveBounce;
  93.             copy.AdaptiveBounceMinEdgeLength = AdaptiveBounceMinEdgeLength;
  94.             copy.AdaptiveBounceThreshold = AdaptiveBounceThreshold;
  95.             copy.AdaptiveBounceMaxSubdiv = AdaptiveBounceMaxSubdiv;
  96.             copy.OutputMesh = OutputMesh;
  97.             copy.IsBinaryOutputXFile = IsBinaryOutputXFile;
  98.         
  99.             // Compression options
  100.             copy.IsSaveCompressedResults = IsSaveCompressedResults;
  101.             copy.Quality = Quality;
  102.             copy.NumberClusters = NumberClusters;
  103.             copy.NumberPcaVectors = NumberPcaVectors;
  104.  
  105.             return copy;
  106.         }
  107.     };
  108.  
  109.     class PrtSimulatorException : DirectXSampleException
  110.     {
  111.         public PrtSimulatorException() : base("Exception in the PrtSimulator class.") {}
  112.         public PrtSimulatorException(string errorDescription) : base(errorDescription) {}
  113.         public PrtSimulatorException(Exception inner) : base("Exception in the PrtSimulator class.", inner) {}
  114.     }
  115.  
  116.  
  117.     class PrtSimulator
  118.     {
  119.         #region Statics
  120.         private static object SyncObject = new object();
  121.         private PrtEngineCallback EngineCallback = null;
  122.         #endregion
  123.  
  124.         #region Instance Data
  125.         private float percentDone = 0.0f;
  126.         private int currentPass = 1;
  127.         private string currentPassName = String.Empty;
  128.         private int numberPasses = 1;
  129.  
  130.         private bool isRunning = false;
  131.         private bool isStopSimulator = false;
  132.  
  133.         private Device device;
  134.         private SimulatorOptions options;
  135.  
  136.         private PrtEngine prtEngine = null;
  137.         private PrtMesh prtMesh = null;
  138.  
  139.         public Thread thread = null;
  140.         private string threadName = String.Empty;
  141.  
  142.         #endregion
  143.  
  144.         #region Simple Properties/Methods
  145.  
  146.         public bool IsRunning { get { return isRunning = (thread != null) && thread.IsAlive; } }
  147.         public float PercentComplete { get { return percentDone * 100.0f; } }
  148.         public int CurrentPass { get { return currentPass; } }
  149.         public string CurrentPassName { get { return currentPassName; } }
  150.         public int NumPasses { get { return numberPasses; } }
  151.  
  152.         #endregion
  153.  
  154.         #region Creation
  155.  
  156.         public PrtSimulator()
  157.         {
  158.         }
  159.  
  160.         #endregion
  161.  
  162.         public void Dispose()
  163.         {
  164.             if(prtEngine != null)
  165.             {
  166.                 prtEngine.Dispose();
  167.                 prtEngine = null;
  168.             }
  169.             if(prtMesh != null)
  170.             {
  171.                 prtMesh.Dispose();
  172.                 prtMesh = null;
  173.             }
  174.         }
  175.  
  176.         public void Run(Device deviceLocal, SimulatorOptions optionsLocal, PrtMesh prtMeshLocal)
  177.         {
  178.             if( IsRunning ) 
  179.                 throw new PrtSimulatorException("Simulator is running when Run is called again");
  180.  
  181.             device = deviceLocal;
  182.             options = optionsLocal.Clone();
  183.             prtMesh = prtMeshLocal;
  184.  
  185.             isRunning = true;
  186.             isStopSimulator = false;
  187.             percentDone = 0.0f;
  188.  
  189.             // Launch the Prt simulator on another thread cause it'll 
  190.             // likely take a while and the UI would be unresponsive otherwise
  191.             thread = new Thread(new ThreadStart(PrtSimulationThreadProc));
  192.             thread.Start();
  193.         }
  194.  
  195.         public void Stop()
  196.         {
  197.             if( IsRunning )
  198.             {
  199.                 lock(SyncObject)
  200.                 {
  201.                     isStopSimulator = true;
  202.                 }
  203.  
  204.                 // Wait for it to close
  205.                 if(thread.Join(10000) == false)
  206.                     throw new PrtSimulatorException("PrtSimulation Thread hasn't exited");
  207.  
  208.                 isStopSimulator = false;
  209.             }
  210.         }
  211.  
  212.         public void PrtSimulationThreadProc()
  213.         {
  214.             // Reset precent complete
  215.             percentDone = 0.0f;
  216.  
  217.             if( !prtMesh.IsMeshLoaded )
  218.                 throw new PrtSimulatorException("Mesh not loaded");
  219.  
  220.             PrtBuffer dataTotal = null;
  221.             PrtBuffer bufferA = null;
  222.             PrtBuffer bufferB = null;
  223.             SphericalHarmonicMaterial[] shMaterials = null;
  224.  
  225.             numberPasses = options.NumberBounces;
  226.             if( options.IsSubsurfaceScattering )
  227.                 numberPasses *= 2;
  228.             if( options.IsAdaptive && options.IsRobustMeshRefine )
  229.                 numberPasses++;
  230.  
  231.             numberPasses += 2;
  232.  
  233.             currentPass = 1;
  234.             percentDone = -1.0f;
  235.             currentPassName = "Initializing PRT engine";
  236.  
  237.             Mesh mesh = prtMesh.Mesh;
  238.  
  239.             bool extractUVs = false;
  240.             if( options.IsAdaptive && prtMesh.AlbedoTexture != null )
  241.                 extractUVs = true;
  242.  
  243.             prtEngine = new PrtEngine(mesh, extractUVs, null);
  244.  
  245.             EngineCallback = new PrtEngineCallback(PrtSimulatorCB);
  246.             prtEngine.SetCallback(EngineCallback, 0.001f);
  247.             prtEngine.SetSamplingInfo( options.NumberRays, false, true, false, 0.0f );
  248.  
  249.             if( options.IsAdaptive && prtMesh.AlbedoTexture != null )
  250.             {
  251.                 prtEngine.SetPerTexelAlbedo( prtMesh.AlbedoTexture, options.NumberChannels, null);
  252.             }
  253.  
  254.             int numberMeshes = mesh.GetAttributeTable().Length;
  255.  
  256.             // This sample treats all subsets as having the same 
  257.             // material properties but they don't have too
  258.             ExtendedMaterial[] material = prtMesh.Materials;
  259.             shMaterials = new SphericalHarmonicMaterial[numberMeshes];
  260.             for( int i = 0; i < numberMeshes; ++i )
  261.             {
  262.                 shMaterials[i].Diffuse = Color.FromArgb(options.Diffuse.ToArgb());
  263.                 shMaterials[i].IsMirror = false;
  264.                 shMaterials[i].IsSubsurfaceScattering = options.IsSubsurfaceScattering;
  265.                 shMaterials[i].RelativeIndexOfRefraction  = options.RelativeIndexOfRefraction;
  266.                 shMaterials[i].Absorption = Color.FromArgb(options.Absorption.ToArgb());
  267.                 shMaterials[i].ReducedScattering = Color.FromArgb(options.ReducedScattering.ToArgb());
  268.  
  269.                 shMaterials[i].Diffuse = prtMesh.Materials[i].Material3D.Diffuse;
  270.             }
  271.  
  272.             bool setAlbedoFromMaterial = true;
  273.             if( options.IsAdaptive && prtMesh.AlbedoTexture != null )
  274.                 setAlbedoFromMaterial = false;
  275.  
  276.             prtEngine.SetMeshMaterials(shMaterials, options.NumberChannels, setAlbedoFromMaterial, options.LengthScale);
  277.  
  278.             if( !options.IsSubsurfaceScattering )
  279.             {
  280.                 // Not doing subsurface scattering
  281.  
  282.                 if( options.IsAdaptive && options.IsRobustMeshRefine ) 
  283.                 {
  284.                     currentPass++;
  285.                     percentDone = -1.0f;
  286.                     currentPassName = "Robust Mesh Refine";
  287.                     prtEngine.RobustMeshRefine( options.RobustMeshRefineMinEdgeLength, options.RobustMeshRefineMaxSubdiv );
  288.                 }
  289.  
  290.                 int numberSamples = prtEngine.NumberVertices;
  291.                 dataTotal = new PrtBuffer(numberSamples, options.Order * options.Order, options.NumberChannels);
  292.  
  293.                 currentPass++;
  294.                 currentPassName = "Computing Direct Lighting";
  295.                 percentDone = 0.0f;
  296.                 if( options.IsAdaptive && options.IsAdaptiveDL )
  297.                 {
  298.                     try 
  299.                     {
  300.                         prtEngine.ComputeDirectLightingSphericalHarmonicsAdaptive(options.Order, options.AdaptiveDLThreshold, options.AdaptiveDLMinEdgeLength, options.AdaptiveDLMaxSubdiv, dataTotal);
  301.                     }
  302.                     catch
  303.                     {
  304.                         goto LEarlyExit;
  305.                     }
  306.                 }
  307.                 else
  308.                 {
  309.                     try 
  310.                     {
  311.                         prtEngine.ComputeDirectLightingSphericalHarmonics(options.Order, dataTotal);
  312.                     }
  313.                     catch
  314.                     {
  315.                         goto LEarlyExit;
  316.                     }
  317.                 }
  318.  
  319.                 if( options.NumberBounces > 1 )
  320.                 {
  321.                     numberSamples = prtEngine.NumberVertices;
  322.                     bufferA = new PrtBuffer(numberSamples, options.Order * options.Order, options.NumberChannels);
  323.                     bufferB = new PrtBuffer(numberSamples, options.Order * options.Order, options.NumberChannels);
  324.                     bufferA.AddBuffer(dataTotal);
  325.                 }
  326.  
  327.                 for( uint bounce = 1; bounce < options.NumberBounces; ++bounce )
  328.                 {
  329.                     currentPass++;
  330.                     currentPassName = string.Format("Computing Bounce {0} Lighting", bounce + 1 );
  331.                     percentDone = 0.0f;
  332.                     try
  333.                     {
  334.                         if( options.IsAdaptive && options.IsAdaptiveBounce )
  335.                             prtEngine.ComputeBounceAdaptive(bufferA, options.AdaptiveBounceThreshold, options.AdaptiveBounceMinEdgeLength, options.AdaptiveBounceMaxSubdiv, bufferB, dataTotal);
  336.                         else
  337.                             prtEngine.ComputeBounce( bufferA, bufferB, dataTotal );
  338.                     }
  339.                     catch
  340.                     {
  341.                         goto LEarlyExit; // handle user aborting simulator via callback 
  342.                     }
  343.  
  344.                     // Swap pBufferA and pBufferB
  345.                     PrtBuffer bufferTemp;
  346.                     bufferTemp = bufferA;
  347.                     bufferA = bufferB;
  348.                     bufferB = bufferTemp;
  349.                 }
  350.  
  351.                 if( options.IsAdaptive )
  352.                 {
  353.                     mesh = prtEngine.GetAdaptedMesh( device);
  354.                     prtMesh.SetMesh(device, mesh);
  355.  
  356.                     XFileFormat xFileFormat;
  357.                     if( options.IsBinaryOutputXFile )
  358.                         xFileFormat = XFileFormat.Binary;
  359.                     else 
  360.                         xFileFormat = XFileFormat.Text;
  361.  
  362.                     // Save the mesh
  363.                     prtMesh.Mesh.Save(options.OutputMesh, (int []) null, prtMesh.Materials, xFileFormat);
  364.                 }
  365.  
  366.                 if(bufferA != null)
  367.                     bufferA.Dispose();
  368.  
  369.                 if(bufferB != null)
  370.                     bufferB.Dispose();
  371.             }
  372.             else
  373.             {
  374.                 // Doing subsurface scattering
  375.  
  376.                 if( options.IsAdaptive && options.IsRobustMeshRefine ) 
  377.                     prtEngine.RobustMeshRefine( options.RobustMeshRefineMinEdgeLength, options.RobustMeshRefineMaxSubdiv );
  378.  
  379.                 int numberSamples = prtEngine.NumberVertices;
  380.                 bufferA = new PrtBuffer(numberSamples, options.Order * options.Order, options.NumberChannels);
  381.                 bufferB = new PrtBuffer(numberSamples, options.Order * options.Order, options.NumberChannels);
  382.                 dataTotal = new PrtBuffer(numberSamples, options.Order * options.Order, options.NumberChannels);
  383.  
  384.                 currentPass = 1;
  385.                 currentPassName = "Computing Direct Lighting";
  386.                 percentDone = 0.0f;
  387.                 if( options.IsAdaptive && options.IsAdaptiveDL )
  388.                 {
  389.                     try
  390.                     {
  391.                         prtEngine.ComputeDirectLightingSphericalHarmonicsAdaptive(options.Order, options.AdaptiveDLThreshold, options.AdaptiveDLMinEdgeLength, options.AdaptiveDLMaxSubdiv, bufferA);
  392.                     }
  393.                     catch
  394.                     {
  395.                         goto LEarlyExit; // handle user aborting simulator via callback 
  396.                     }
  397.                 }
  398.                 else
  399.                 {
  400.                     try
  401.                     {
  402.                         prtEngine.ComputeDirectLightingSphericalHarmonics( options.Order, bufferA );
  403.                     }
  404.                     catch
  405.                     {
  406.                         goto LEarlyExit; // handle user aborting simulator via callback 
  407.                     }
  408.                 }
  409.  
  410.                 currentPass++;
  411.                 currentPassName = "Computing Subsurface Direct Lighting";
  412.                 try
  413.                 {
  414.                     prtEngine.ComputeSubsurfaceScattering( bufferA, bufferB, dataTotal );
  415.                 }
  416.                 catch
  417.                 {
  418.                     goto LEarlyExit; // handle user aborting simulator via callback 
  419.                 }
  420.  
  421.                 for( uint bounce = 1; bounce < options.NumberBounces; ++bounce )
  422.                 {
  423.                     currentPass++;
  424.                     currentPassName = string.Format("Computing Bounce {0} Lighting", bounce + 1);
  425.                     percentDone = 0.0f;
  426.                     try
  427.                     {
  428.                         if( options.IsAdaptive && options.IsAdaptiveBounce )
  429.                             prtEngine.ComputeBounceAdaptive( bufferB, options.AdaptiveBounceThreshold, options.AdaptiveBounceMinEdgeLength, options.AdaptiveBounceMaxSubdiv, bufferA, null);
  430.                         prtEngine.ComputeBounce( bufferA, bufferB, dataTotal );
  431.                     }
  432.                     catch
  433.                     {
  434.                         goto LEarlyExit; // handle user aborting simulator via callback 
  435.                     }
  436.  
  437.                     currentPass++;
  438.                     currentPassName = string.Format("Computing Subsurface Bounce {0} Lighting", bounce + 1 );
  439.                     try
  440.                     {
  441.                         prtEngine.ComputeSubsurfaceScattering( bufferB, bufferA, dataTotal );
  442.                     }
  443.                     catch
  444.                     {
  445.                         goto LEarlyExit; // handle user aborting simulator via callback 
  446.                     }
  447.                 }
  448.  
  449.                 if( options.IsAdaptive )
  450.                 {
  451.                     mesh = prtEngine.GetAdaptedMesh( device);
  452.                     prtMesh.SetMesh(device, mesh);
  453.  
  454.                     XFileFormat xFileFormat;
  455.                     if( options.IsBinaryOutputXFile )
  456.                         xFileFormat = XFileFormat.Binary;
  457.                     else 
  458.                         xFileFormat = XFileFormat.Text;
  459.  
  460.                     // Save the mesh
  461.                     prtMesh.Mesh.Save(options.OutputMesh, (int []) null, prtMesh.Materials, xFileFormat);
  462.                 }
  463.  
  464.                 if(bufferA != null)
  465.                     bufferA.Dispose();
  466.  
  467.                 if(bufferB != null)
  468.                     bufferB.Dispose();
  469.             }
  470.  
  471.             currentPass++;
  472.             currentPassName = "Compressing Buffer";
  473.             percentDone = -1.0f;
  474.  
  475.             Directory.SetCurrentDirectory( options.InitialDir );
  476.             prtMesh.SetPrtBuffer( dataTotal, options.ResultsFileName );
  477.             prtMesh.CompressBuffer(CompressionQuality.FastLowQuality, 1, 24);
  478.  
  479.             if( options.IsSaveCompressedResults )
  480.             {
  481.                 PrtCompressedBuffer compBuffer = prtMesh.CompressedBuffer;
  482.                 compBuffer.Save(options.ResultsFileName);
  483.             }
  484.             else
  485.             {
  486.                 dataTotal.Save(options.ResultsFileName);
  487.             }
  488.             prtMesh.ExtractCompressedDataForPrtShader();
  489.  
  490.             isRunning = false;
  491.             percentDone = 1.0f;
  492.  
  493.             if(prtEngine != null)
  494.             {
  495.                 prtEngine.Dispose();
  496.                 prtEngine = null;
  497.             }
  498.  
  499.             return;
  500.  
  501.             LEarlyExit:
  502.  
  503.             // Usually fails becaused user stoped the simulator
  504.             isRunning = false;
  505.  
  506.             if(prtEngine != null)
  507.                 prtEngine.Dispose();
  508.  
  509.             if(bufferA != null)
  510.                 bufferA.Dispose();
  511.  
  512.             if(bufferB != null)
  513.                 bufferB.Dispose();
  514.  
  515.             if(dataTotal != null)
  516.                 dataTotal.Dispose();
  517.         }
  518.  
  519.  
  520.         /// <summary>
  521.         /// records the percent done and stops the simulator if requested
  522.         /// </summary>
  523.         private bool PrtSimulatorCB( float simulatorPercentage )
  524.         {
  525.             lock(SyncObject)
  526.             {
  527.                 // Update percentage
  528.                 percentDone = simulatorPercentage;
  529.  
  530.                 // In this callback, returning false will stop the simulator
  531.                 return (!isStopSimulator);
  532.             }
  533.         }
  534.     }
  535. }
  536.